package com.srwl.mytx.im;

import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.Looper;
import android.text.TextUtils;
import android.util.Log;

import com.alibaba.fastjson.JSONObject;
import com.srwl.mytx.BuildConfig;
import com.srwl.mytx.Constant;
import com.srwl.mytx.MyApplication;
import com.srwl.mytx.activity.MainActivity;
import com.srwl.mytx.im.conversation.Conversation;
import com.srwl.mytx.domain.Message;
import com.srwl.mytx.im.core.IMSClientFactory;
import com.srwl.mytx.im.core.IMSConfig;
import com.srwl.mytx.im.interf.IMSClient;
import com.srwl.mytx.im.interf.MessageSendListener;
import com.srwl.mytx.im.listener.ConnectListener;
import com.srwl.mytx.im.listener.MessageListener;
import com.srwl.mytx.im.protobuf.MessageProtobuf;

import java.util.ArrayList;
import java.util.List;
import java.util.Vector;

/**
 * NettyChat
 */
public class IMSClientBootstrap implements Conversation.MessageUnReadCountListener, MessageListener, ConnectListener {

    private static final String TAG = "IMSClientBootstrap";
    private static IMSClientBootstrap INSTANCE;
    private IMSClient imsClient;
    private boolean isActive;
    private ConversationService conversationService;
    private LiveRoomService liveRoomService;
    private List<ImListener> imListenerList = new ArrayList<>();
    private List<LoginListener> loginListenerList = new ArrayList<>();
    private List<ConnectListener> connectListenerList = new ArrayList<>();
    private List<LogoutListener> logoutListenerList = new ArrayList<>();
    private int totalUnReadCount;
    private Context context;
    private Handler handler = new Handler(Looper.getMainLooper());


    private IMSClientBootstrap() {
        init();
    }

    /**
     * 为什么在init 里面要去创建 ConversationService呢
     * 是因为当某些未知情况，app 在MainActivity 状态下奔溃了，在MainActivity会重建，conversationFragment 也会重建
     * 如果 ConversationService 为空，就会报错了
     * 如果能避免奔溃，或者奔溃后能切换到登录页面，那么是可以不在这儿 创建 ConversationService等服务的
     */
    public void init() {
        this.context = MyApplication.applicationContext;
        //必须判断是否有 用户id存在（也就是判断用户是否曾经已经登录过），如果没有登录过，不去创建 以下几个服务，
        //为什么在 初始化的时候就 开始创建 conversationService，因为游客模式下，后台登录还没完成，用户可能已经打开了聊天页面了
//        if (UserProfileManager.getInstance().getUserID() != null) {
//            conversationService = new ConversationService(context, this);
//
//            liveRoomService = new LiveRoomService();
//        }
    }

    public static IMSClientBootstrap getInstance() {

        if (INSTANCE == null) {
            INSTANCE = new IMSClientBootstrap();
        }

        return INSTANCE;
    }

//    public static void main(String[] args) {
//        String userId = "100001";
//        String token = "token_" + userId;
//        IMSClientBootstrap bootstrap = IMSClientBootstrap.getInstance();
//        String hosts = "[{\"host\":\"127.0.0.1\", \"port\":8866}]";
//        bootstrap.login(userId, token, hosts, 0);
//    }

    /**
     * http登录后才调用
     */
    public synchronized void login() {
        totalUnReadCount = 0;
        notifyUnreadCountChange();
        //登录的时候重建会话服务 不然可能会显示出上一个 在本手机登录用户的会话
        conversationService = new ConversationService(context, this);
        liveRoomService = new LiveRoomService();
        //通知登录完成，监听的地方可以做 联系人列表初始化 会话列表初始化
        notifyLoginStateChange();

        Vector<String> serverUrlList = new Vector<String>();
        serverUrlList.add(BuildConfig.IM_HOST);

        isActive = true;
        Log.i(TAG, "login: login IMLibClientBootstrap, servers=" + BuildConfig.IM_HOST);
        if (null != imsClient) {
            imsClient.close();
        }
        imsClient = IMSClientFactory.getIMSClient();
        updateAppStatus(IMSConfig.APP_STATUS_FOREGROUND);
        imsClient.setMessageListener(this);
        imsClient.setConnectListener(this);
        imsClient.init(serverUrlList, new IMSEventListener(context), new IMSConnectStatusListener());

    }

    public boolean isActive() {
        return isActive;
    }

    /**
     * 发送消息
     *
     * @param msg
     */
    public void sendMessage(MessageProtobuf.Msg msg) {
        if (isActive) {
            imsClient.sendMsg(msg);
        } else {
            Log.e(TAG, "sendMessage: 当前im 链接失活，不尝试发送，按失败处理返回 +msg" + msg.toString());
            handler.post(() -> {
                if (conversationService != null) {
                    conversationService.onMessageSendFail(msg.getHead().getMsgId());
                } else {
                    Log.e(TAG, "sendMessage: conversationService 为空，，，，，，，，，，，");
                }
            });
        }
    }

    public void sendRealTimeMessage(MessageProtobuf.Msg msg, MessageSendListener listener) {
        if (isActive) {
            imsClient.sendRealTimeMessage(msg, listener);
        }
    }

    public void updateAppStatus(int appStatus) {
        if (imsClient == null) {
            return;
        }

        imsClient.setAppStatus(appStatus);
    }

    public ConversationService getConversationService() {
        return conversationService;
    }


    public LiveRoomService getLiveRoomService() {
        return liveRoomService;
    }

    @Override
    public void onReadCountReduce(int count) {
        totalUnReadCount -= count;
        notifyUnreadCountChange();
    }

    @Override
    public void onReadCountAdd(int count) {
        totalUnReadCount += count;
        notifyUnreadCountChange();
    }

    public void logout() {
        Log.i(TAG, "logout: IM 退出登录，清理数据.....");
        handler.post(new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < logoutListenerList.size(); i++) {
                    logoutListenerList.get(i).onImLogout();
                }

            }
        });
        isActive = false;
        if (imsClient != null) {
            imsClient.close();
        }
        if (conversationService != null) {
            conversationService = null;
        }
        liveRoomService = null;
        totalUnReadCount = 0;
    }

    public void addImListener(ImListener imListener) {
        imListenerList.add(imListener);
        notifyUnreadCountChange();
    }

    /**
     * 通知未读数改变
     */
    private void notifyUnreadCountChange() {
        handler.post(() -> {
            if (imListenerList.size() != 0) {
                for (int i = 0; i < imListenerList.size(); i++) {
                    ImListener imListener = imListenerList.get(i);
                    imListener.onUnreadCountChange(totalUnReadCount);
                }
            }
        });
    }

    public void addLoginListenerList(LoginListener loginListener) {
        loginListenerList.add(loginListener);
        if (isActive) {
            loginListener.onRestLoginSuccess();
        }
    }

    private void notifyLoginStateChange() {
        handler.post(() -> {
            for (int i = 0; i < loginListenerList.size(); i++) {
                LoginListener loginInterface = loginListenerList.get(i);
                loginInterface.onRestLoginSuccess();
            }
        });
    }

    public void addConnectListeners(ConnectListener connectListeners) {
        connectListenerList.add(connectListeners);
    }

    public void removeConnectListener(ConnectListener connectListener) {
        connectListenerList.remove(connectListener);
    }

    public void addLogoutListener(LogoutListener logoutListener) {
        logoutListenerList.add(logoutListener);
    }

    public void removeLogoutListener(LogoutListener logoutListener) {
        logoutListenerList.remove(logoutListener);
    }

    /**
     * 接收ims转发过来的消息
     *
     * @param msg
     */
    @Override
    public void dispatchMsg(MessageProtobuf.Msg msg) {
        //  MessageProcessor.getInstance().receiveMsg(MessageBuilder.getMessageByProtobuf(msg));

        int type = msg.getHead().getMsgType();
        switch (type) {
            case Constant.C2C_MESSAGE: {
                Message message = JSONObject.parseObject(msg.getBody(), Message.class);
                conversationService.distributeC2CMessage(message);
                break;
            }

            case Constant.NOTIFY_MESSAGE: {
                Message message = JSONObject.parseObject(msg.getBody(), Message.class);
                conversationService.distributeNotifyMessage(message);

                break;
            }
            case Constant.ACCOUNT_MESSAGE:

                // Helper.getInstance().reset();
                if (TextUtils.equals(msg.getHead().getExtend(), Constant.REPEAT_LOGIN)) {
                    Log.i(TAG, "dispatchMsg: 账户登录冲突  下线处理 ");
                    onConnectionConflict();
                } else {
                    Log.i(TAG, "dispatchMsg: 账户被锁定  下线处理 ");
                    onAccountLock();
                }
                break;

            // TODO: 2019/10/18  发送回执 也应该归为c2e 类型消息
            case Constant.IM_TYPE_SEND_ACK:
                if (Constant.IM_SEND_STATE_SUCCESS == msg.getHead().getStatusReport()) {
                    conversationService.onMessageSendSuccess(msg.getHead().getMsgId());
                } else {
                    conversationService.onMessageSendFail(msg.getHead().getMsgId());
                }
                break;
            case Constant.LIVE_ROOM_MESSAGE: {
                Message message = JSONObject.parseObject(msg.getBody(), Message.class);
                liveRoomService.distributeMessage(message);

                break;
            }
            case Constant.TRIBE_MESSAGE:

                break;
        }

    }

    /**
     * 发送本地消息
     * 本地构造一条消息，然后发给自己
     *
     * @param message
     */
    public void sendLocalMessage(Message message) {
        Integer type = message.getType();
        switch (type) {
            case Constant.C2C_MESSAGE:
                conversationService.distributeC2CMessage(message);
                break;

            case Constant.NOTIFY_MESSAGE:
                conversationService.distributeNotifyMessage(message);
                break;

        }
    }

    @Override
    public void dispatchOffLineMsg(List<Message> messages) {
        //目前离线消息只有用户发个给用户的消息和通知类型的消息做了离线存储，其中点对点消息的消息总分类和大分类是相同的，其他的通知消息，总分类都是  NOTIFY_MESSAGE，
        for (int i = 0; i < messages.size(); i++) {
            Message message = messages.get(i);
            Integer type = message.getType();
            if (type >= Constant.NOTIFY_MESSAGE_SYSTEM) {//通知类消息分类从100 开始
                conversationService.distributeNotifyMessage(message);
            } else {
                conversationService.distributeC2CMessage(message);
            }
        }

    }


    /**
     * 当账户在 其他设备登录  强制退出
     */
    private void onConnectionConflict() {
        Intent intent = new Intent(context, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.putExtra(Constant.ACCOUNT_CONFLICT, true);
        context.startActivity(intent);
    }

    /**
     * 当用户账户被锁定  强制退出
     */
    private void onAccountLock() {
        Intent intent = new Intent(context, MainActivity.class);
        intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        intent.putExtra(Constant.ACCOUNT_LOCK, true);
        context.startActivity(intent);
    }

    private void checkVisible(Message message) {
        Integer visible = message.getVisible();
        if (visible != null && visible == Constant.MESSAGE_VISIBLE) {
            totalUnReadCount++;
            notifyUnreadCountChange();
        }
    }

    public int getTotalUnReadCount() {
        return totalUnReadCount;
    }

    public void clearListener() {
        imListenerList.clear();
        loginListenerList.clear();
    }

    @Override
    public void onReConnectSuccess() {
        conversationService.onConnectSuccess();
        for (ConnectListener connectListener : connectListenerList) {
            connectListener.onReConnectSuccess();
        }
    }

    @Override
    public void onConnectInterruption() {
        for (ConnectListener connectListener : connectListenerList) {
            connectListener.onConnectInterruption();
        }
    }

    @Override
    public void onImLoginSuccess() {
        conversationService.onConnectSuccess();
        for (ConnectListener connectListener : connectListenerList) {
            connectListener.onImLoginSuccess();
        }
    }


    public interface ImListener {

        void onUnreadCountChange(int totalUnReadCount);


    }

    public interface LoginListener {
        /**
         * 并非 im 链接 完成，而只是http登录后端user服务的接口完成,此刻已经返回了登陆者的用户数据和联系人等数据，
         * 如果需要 im 登录完成的回调，应该在 com.srwl.mytx.im.listener.MessageListener 接口中，细分 登录完成 或者重连完成 ，再分发出来
         */
        void onRestLoginSuccess();
    }

    public interface LogoutListener {
        void onImLogout();
    }
}
